﻿//    TestGenerator - experiment with piping data into ffmpeg in "pipefmt"
//    Copyright (C) 2012  Juergen Bohl

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace TestGenerator
{
    #region using directives
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Text;
    #endregion

    class BitmapGeneratorOptions : ICloneable
    {
        private int startValue;
        private int stopValue;

        private int width;
        private int height;

        public int StartValue
        {
            get { return startValue; }
            set { startValue = value; }
        }

        public int StopValue
        {
            get { return stopValue; }
            set { stopValue = value; }
        }

        public int Width
        {
            get { return width; }
            set { width = value; }
        }

        public int Height
        {
            get { return height; }
            set { height = value; }
        }

        public object Clone()
        {
            return new BitmapGeneratorOptions()
                       {
                           StartValue = this.StartValue,
                           StopValue = this.StopValue
                       };
        }
    }

    public abstract class LockInfo
    {
        public abstract IntPtr Ptr { get; }

        public abstract int Stride { get; }

        public abstract int Width { get; }

        public abstract int Height { get; }

        public abstract int Size { get; }
    }

    class BitmapGenerator
    {
        private Graphics graphics;
        private Bitmap bitmap;

        private Font font;

        private int counter;

        public void Init(BitmapGeneratorOptions options)
        {
            this.bitmap = new Bitmap(
                                    options.Width,
                                    options.Height,
                                    System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            this.graphics = Graphics.FromImage(this.bitmap);

            // choose size of font so that five characters fit well
            int fontSizeX = options.Width / 6;
            int fontSizeY = options.Height / 3;
            int fontSize = Math.Min(fontSizeX, fontSizeY);
            this.font = new System.Drawing.Font("Arial", fontSize, GraphicsUnit.Pixel);
        }

        public void GenerateNext()
        {
            this.GenerateImage();
        }

        public LockInfo Lock()
        {
            BitmapData bmData = this.bitmap.LockBits(
                                                new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height),
                                                ImageLockMode.ReadOnly,
                                                PixelFormat.Format24bppRgb);
            return new InternalLockInfo(bmData, this.bitmap.Width, this.bitmap.Height);
        }

        public void Unlock(LockInfo lockInfo)
        {
            InternalLockInfo internalLockInfo = (InternalLockInfo)lockInfo;
            this.bitmap.UnlockBits(internalLockInfo.BitmapData);
        }

        private void GenerateImage()
        {
            this.graphics.Clear(Color.Blue);
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("{0}", ++this.counter);

            this.graphics.DrawString(
                            sb.ToString(),
                            this.font,
                            new SolidBrush(Color.Red),
                            new Point(10, 100));
        }

        protected class InternalLockInfo : LockInfo
        {
            private int width, height;
            private BitmapData bitmapData;

            public InternalLockInfo(BitmapData bmData, int w, int h)
            {
                this.bitmapData = bmData;
                this.width = w;
                this.height = h;
            }

            public override IntPtr Ptr
            {
                get { return this.bitmapData.Scan0; }
            }

            public override int Stride
            {
                get { return this.bitmapData.Stride; }
            }

            public override int Width
            {
                get { return this.width; }
            }

            public override int Height
            {
                get { return this.height; }
            }

            public override int Size
            {
                get { return this.Stride * this.Height; }
            }

            public BitmapData BitmapData
            {
                get { return this.bitmapData; }
            }
        }
    }
}
